package futbol

import org.junit.Assert
import org.junit.Before
import org.junit.Test

import static org.mockito.Matchers.*
import static org.mockito.Mockito.*

class TestObservers {
	
	Jugador jugadorA
	Jugador jugadorB
	Partido partido
	ObserverAmigos amigos
	ObserverPunisher punisher
	ObserverSomosDiez dies
	Estandar estandar
	
	@Before
	def void init(){
	estandar = new Estandar
	jugadorA= new Jugador
	jugadorA.estado =  estandar 
	partido= new Partido
	punisher= new ObserverPunisher
	amigos= new ObserverAmigos
	dies= new ObserverSomosDiez
	
	
	}
	
	/////////////////////////////////////////////////////////////////////////////
	/*    test para comprobar el normal funcionamiento de los observer      */
	////////////////////////////////////////////////////////////////////////////
	
	
	@Test //test para comprobar si el observer amigo puede inscibir jugadores normalmente
	def void agregarJugadoresConObserver(){
		var mockedMailSender = mock(typeof(MailSender))
		amigos.mailSender =  mockedMailSender
		partido.agregaObservers(amigos)
		 //aca agrego observers
		
		jugadorA.inscribirmeAPartido(partido)
		
	}
	
	/////////////////////////////////////////////////////////////////////////////
	/*          test para comprobar las funciones de los observers           */
	////////////////////////////////////////////////////////////////////////////
	
	
	
	@Test //test para comprobar si funciona el observer de amigos
	def void observerMensajeAmigos (){
		var mockedMailSender = mock(typeof(MailSender))
		amigos.mailSender =  mockedMailSender
		partido.agregaObservers(amigos)
		
		//le doy x amigos a jugador
		var x=0
		while(x != 5){
			jugadorA.agregarAmigo(new Jugador)
			x = x+1
		}
		
		Assert::assertEquals(5,jugadorA.amigosSize,0.01)
		jugadorA.inscribirmeAPartido(partido)
		//pruebo

		verify(mockedMailSender, times(5)).enviaMail(any(typeof(Mail)))
		
		//una segunda prueba para probar la collection correctamente
		
		jugadorB= new Jugador
		jugadorB.estado= estandar 
		x=0
		while(x != 5){
			jugadorB.agregarAmigo(new Jugador)
			x = x+1
		}
		jugadorB.inscribirmeAPartido(partido)
		//pruebo
		verify(mockedMailSender, times(10)).enviaMail(any(typeof(Mail)))
		
	} 
	
	@Test //test para comprobar si funciona el observer punisher
	def void observerMensajePunisher (){
		var mockedMailSender = mock(typeof(MailSender))
		punisher.mailSender =  mockedMailSender
		partido.agregaObservers(punisher)
		
		//aca puebo si no envia el mensaje cuando no debe
		jugadorA.inscribirmeAPartido(partido)
		Assert::assertEquals(1,partido.cantidadDeJugadoresActuales(), 0.01)
		jugadorA.bajateDeUnPartido(partido, null) //la variable q dejo en null es el remplazo
		verify(mockedMailSender, times(0)).enviaMail(any(typeof(Mail)))
		Assert::assertEquals(0,partido.cantidadDeJugadoresActuales(), 0.01)
		//primero agrego 9 jugadores
		
		var x=0
		while(x != 9){
			var dummyJugador= new Jugador
			dummyJugador.estado= estandar
			dummyJugador.inscribirmeAPartido(partido)
			x = x+1
		}
		
		//aca compruebo que si lo envie
		jugadorA.inscribirmeAPartido(partido)
		jugadorA.bajateDeUnPartido(partido, null)
		verify(mockedMailSender, times(1)).enviaMail(any(typeof(Mail)))
		
	} 
	
	@Test //test para comprobar si funciona el observer de somos dies
	def void observerSomosDies (){
		var mockedMailSender = mock(typeof(MailSender))
		dies.mailSender =  mockedMailSender
		partido.agregaObservers(dies)
		//le doy x amigos a jugador
		var x=0
		while(x != 10){
			var dummyJugador= new Jugador
			dummyJugador.estado= estandar
			dummyJugador.inscribirmeAPartido(partido)
			x = x+1
		}
		verify(mockedMailSender, times(1)).enviaMail(any(typeof(Mail)))
		
	} 
	
	/////////////////////////////////////////////////////////////////////////////
	/*          tests para ver la interaccion entre decorators                */
	////////////////////////////////////////////////////////////////////////////
	
	
	@Test //compruebo si no hay problemas en el acoplamiento en el comportamiento de somos dies
	def void decorarSomosdiesAcoplado(){
		partido.agregaObservers(amigos)
		partido.agregaObservers(dies)
		partido.agregaObservers(punisher)
		
		var mockedMailSender = mock(typeof(MailSender))
		punisher.mailSender =  mockedMailSender
		amigos.mailSender =  mockedMailSender
		dies.mailSender =  mockedMailSender
		
		var x=0
		while(x < 10){
			var dummyJugador= new Jugador
			dummyJugador.estado= estandar
			dummyJugador.inscribirmeAPartido(partido)
			x = x+1
		}
		verify(mockedMailSender, times(1)).enviaMail(any(typeof(Mail)))
	}  
	
	@Test //compruebo si no hay problemas en el comportamiento de observers
	def void decorarPunisherAcoplado(){
		partido.agregaObservers(amigos)
		partido.agregaObservers(dies)
		partido.agregaObservers(punisher)
		
		var mockedMailSender = mock(typeof(MailSender))
		punisher.mailSender =  mockedMailSender
		amigos.mailSender =  mockedMailSender
		dies.mailSender =  mockedMailSender
		
		//aca puebo si no envia el mensaje cuando no debe
		jugadorA.inscribirmeAPartido(partido)
		jugadorA.bajateDeUnPartido(partido, null) //la variable q dejo en null es el remplazo
		verify(mockedMailSender, times(0)).enviaMail(any(typeof(Mail)))
		
		//primero agrego 9 jugadores
		var x=0
		while(x != 9){
			var dummyJugador= new Jugador
			dummyJugador.estado= estandar
			dummyJugador.inscribirmeAPartido(partido)
			x = x+1
		}
		
		//aca compruebo que si lo envie
		jugadorA.inscribirmeAPartido(partido)
		jugadorA.bajateDeUnPartido(partido, null)
		verify(mockedMailSender, times(2)).enviaMail(any(typeof(Mail)))
		//son 2 mensajes, uno porque llegaron a ser 10 y uno porque se bajo
		
	}
	@Test //compruebo si no hay problemas comportamiento de amigos
	def void decorarAmigosAcoplado(){
		partido.agregaObservers(amigos)
		partido.agregaObservers(dies)
		partido.agregaObservers(punisher)
		
		var mockedMailSender = mock(typeof(MailSender))
		punisher.mailSender =  mockedMailSender
		amigos.mailSender =  mockedMailSender
		dies.mailSender =  mockedMailSender
		
		//le doy x amigos a jugador
		
		var x=0
		while(x != 5){
			jugadorA.agregarAmigo(new Jugador)
			x = x+1
		}
		Assert::assertEquals(5,jugadorA.amigosSize,0.01)
		jugadorA.inscribirmeAPartido(partido)
		
		//pruebo
		verify(mockedMailSender, times(5)).enviaMail(any(typeof(Mail)))
	}
}